package jatosoft.accounting.dao.hibernate;

import jatosoft.accounting.dao.VoucherDao;
import jatosoft.accounting.dao.model.Account;
import jatosoft.accounting.dao.model.Voucher;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

public class VoucherHibernate extends BaseHibernateDao implements VoucherDao {

	public Integer insert(Voucher v) {
		return (Integer) hibernateTemplate.save(v);
	}

	@SuppressWarnings("unchecked")
	public List<Voucher> queryByDateDuration(Date fromDate, Date toDate) {
		Criteria critDuration = SessionFactoryUtils.getSession(
				hibernateTemplate.getSessionFactory(), true).createCriteria(
				Voucher.class);
		critDuration.add(Restrictions.between("voucherDate", fromDate, toDate));
		critDuration.addOrder(Order.asc("voucherDate"));
		// SortedSet results = new TreeSet(critDuration.list());
		// return new ArrayList(results);
		return critDuration.list();
	}

	public void deleteVoucher(Voucher voucher) {
		hibernateTemplate.delete(voucher);
	}

	public List sumAmountByAccount(Date fromDate, Date toDate) {
		Criteria crit = SessionFactoryUtils.getSession(
				hibernateTemplate.getSessionFactory(), true).createCriteria(
				Voucher.class);
		crit.createAlias("voucherItemList", "vi", Criteria.INNER_JOIN);
		crit.setProjection(Projections.projectionList().add(
				Projections.sum("vi.amount")).add(
				Projections.groupProperty("vi.account")));
		crit.add(Restrictions.between("voucherDate", fromDate, toDate));
		crit.addOrder(Order.asc("vi.account.id"));
		return crit.list();

	}

	public Voucher getVoucher(Integer voucherId) {
		Voucher v = hibernateTemplate.get(Voucher.class, voucherId);
		Hibernate.initialize(v.getVoucherItemList());
		return v;
	}

	public Double sumByAccount(Account account, int year, int month) {
		Criteria crit = SessionFactoryUtils.getSession(
				hibernateTemplate.getSessionFactory(), true).createCriteria(
				Voucher.class);
		crit.createAlias("voucherItemList", "vi", Criteria.INNER_JOIN);
		crit.setProjection(Projections.projectionList().add(
				Projections.sum("vi.amount")));
		crit.add(Restrictions.like("vi.account.accountId", account.getAccountId()+"%"));
		Calendar cs = Calendar.getInstance();
		cs.clear();
		cs.set(year, month-1, 1);
//		cs.set(Calendar.YEAR, year);
//		cs.set(Calendar.MONTH, month - 1);
//		cs.set(Calendar.DATE, cs.getMinimum(Calendar.DAY_OF_MONTH));
//		cs.set(Calendar.HOUR, cs.getMinimum(Calendar.HOUR_OF_DAY));
//		cs.set(Calendar.MINUTE, cs.getMinimum(Calendar.MINUTE));
//		cs.set(Calendar.SECOND, cs.getMinimum(Calendar.SECOND));

		Calendar ce = Calendar.getInstance();
		ce.clear();
		ce.set(Calendar.YEAR, year);
		ce.set(Calendar.MONTH, month - 1);
		ce.set(Calendar.DATE, ce.getActualMaximum(Calendar.DAY_OF_MONTH));
		ce.set(Calendar.HOUR, ce.getActualMaximum(Calendar.HOUR_OF_DAY));
		ce.set(Calendar.MINUTE, ce.getActualMaximum(Calendar.MINUTE));
		ce.set(Calendar.SECOND, ce.getActualMaximum(Calendar.SECOND));

		crit.add(Restrictions
				.between("voucherDate", cs.getTime(), ce.getTime()));
		Double value = (Double) crit.list().get(0);
		return value == null ? 0 : value;

	}
}
